﻿using SolidEdgeFramework;
using SolidEdgePart;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using TGCommunity;
using System.Collections.ObjectModel;
using TGComacAddin.View;
using System.ComponentModel;
using System.Windows.Interop;

namespace TGComacAddin.command
{
    public enum FaceChainMode
    {
        Chain=0, //链或壳
        Single = 1, // 单一
    }
    public interface ISelectOptionChang
    {
        void OnOptionChange(FaceChainMode mode);
    }
    public enum GeomType
    {
        vf_vertex = 1,
        vf_curve = 1 << 1,
        vf_face = 1 << 2,
        vf_loop = 1 << 3,
        vf_body = 1 << 4,
    }
    public  enum SelectStatus
    {
        Success,
        Cancel,
        Running,
        Failed,
    };


    public class ElementDesc : INotifyPropertyChanged
    {
        private UInt64 _id;
        public UInt64 Id
        {
            get { return _id; }
            set
            {
                _id = value;
                OnPropertyChanged(nameof(Id));
                
            }
        }
        #region 实现INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion 实现INotifyPropertyChanged

        public Object Geometry;

        private SolidEdgeGeometry.GNTTypePropertyConstants _type;
        public SolidEdgeGeometry.GNTTypePropertyConstants Type
        {
            get { return _type; }
            set
            {
                _type = value;
                OnPropertyChanged(nameof(Type));
                
            }
        }

        private string GetDisplayName()
        {
            string str = "";
            switch (_type)
            {
                case SolidEdgeGeometry.GNTTypePropertyConstants.igVertex:
                    str = "点";
                    break;
                case SolidEdgeGeometry.GNTTypePropertyConstants.igEdge:
                    str = "线";
                    break;
                case SolidEdgeGeometry.GNTTypePropertyConstants.igFace:
                    str = "面";
                    break;

                case SolidEdgeGeometry.GNTTypePropertyConstants.igLoop:
                    str = "环";
                    break;
                case SolidEdgeGeometry.GNTTypePropertyConstants.igBody:
                    str = "体";
                    break;
                default:
                    str = "未知";
                    break;
            }

            str += " " + Id.ToString();
            return str;
        }


        private string _displayName = "";
        public string DisplayName
        {
            get {
                _displayName = GetDisplayName();
                return _displayName; 
            }
            set
            {
                _displayName = value;
                OnPropertyChanged(nameof(DisplayName));
                
            }
        }

    }

    public class ElementsViewModel : INotifyPropertyChanged
    {
        #region 实现INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion 实现INotifyPropertyChanged

        private ObservableCollection<ElementDesc> _eleDescArr = new ObservableCollection<ElementDesc>();
        public ObservableCollection<ElementDesc> ElementDescArr
        {
            get { return _eleDescArr; }
            set {
              _eleDescArr = value;
                OnPropertyChanged(nameof(ElementDescArr));
            }
        }

        public ElementsViewModel( ObservableCollection<ElementDesc> eleDescArr)
        {
            _eleDescArr = eleDescArr;
        }
    }

    public class TGSelect : SolidEdgeFramework.ISECommandEvents, SolidEdgeFramework.ISEMouseEvents, SolidEdgeFramework.ISELocateFilterEvents,IDisposable, ISelectOptionChang
    {
        private ConnectionPointController _connectController;
        private SolidEdgeFramework.Mouse _mouse = null;
        private PartDocument _partDoc=null;
        private string _prompStr = "";
        private int _filterType = 0;

        private bool _isSingleSelect = false;

        private ObservableCollection<ElementDesc> _eleIdArr = new ObservableCollection<ElementDesc>();
        public ObservableCollection<ElementDesc> ElementIds
        {
            get { return _eleIdArr; }
            set { _eleIdArr = value; }
        }

        private SelectStatus _status = SelectStatus.Running;
        public SelectStatus Status
        {
            get { return _status; }
            set { _status = value; }
        }

        /// <summary>
        /// 连接事件源
        /// </summary>
        private void ConnectEventSource()
        {
          
        }

        /// <summary>
        /// 断开事件源
        /// </summary>
        private void DisconnectEventSource()
        {
            _connectController.UnadviseAllSinks();
        }

        private ElementsViewModel _viewModel = null;
        private View.SelectOption _selOpt = null;

        public TGSelect(SolidEdgeFramework.Mouse mouse, SolidEdgeFramework.Command cmd,PartDocument partDoc, string prompStr, int filterType, bool isSingleSelect)
        {
            _partDoc = partDoc;
            _connectController = new ConnectionPointController(this);
            _connectController.AdviseSink<SolidEdgeFramework.ISEMouseEvents>(mouse);
            _connectController.AdviseSink<SolidEdgeFramework.ISECommandEvents>(cmd);
            _connectController.AdviseSink<SolidEdgeFramework.ISELocateFilterEvents>(mouse);

            ConnectEventSource();
            _mouse = mouse;
            _prompStr = prompStr;
            _filterType = filterType;
            _isSingleSelect = isSingleSelect;

            if(!_isSingleSelect)
            {
                _viewModel = new ElementsViewModel(_eleIdArr);
                TGSelectedItemsDlg dlg = new TGSelectedItemsDlg(_viewModel, _partDoc, this);
                dlg.Show();
                _partDoc.Application.ActiveSelectSet.RemoveAll();
            }
            _selOpt = new View.SelectOption(this);

        }


        [DllImport("user32.dll")]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
        public const uint SWP_NOSIZE = 0x0001;
        public const uint SWP_NOMOVE = 0x0002;
        public const uint SWP_NOACTIVATE = 0x0010;

        void SolidEdgeFramework.ISECommandEvents.Activate()
        {

            _mouse.ScaleMode = 1;                // Design model coordinates.
            _mouse.WindowTypes = 1;              // Graphic window's only please.
            _mouse.EnabledDrag = true;
            _mouse.EnabledMove = true;   // Request move events.
            _mouse.LocateMode = (int)SolidEdgeConstants.seLocateModes.seLocateSimple;
            _mouse.ClearLocateFilter();
            if ((_filterType & (int)GeomType.vf_vertex) > 0)
            {
                _mouse.AddToLocateFilter((int)SolidEdgeConstants.seLocateFilterConstants.seLocateVertex);
            }
            if ((_filterType & (int)GeomType.vf_curve) > 0)
            {
                _mouse.AddToLocateFilter((int)SolidEdgeConstants.seLocateFilterConstants.seLocateEdge);
                // 置为1，使选择链
                _mouse.GroupLocateMode = 1;
            }
            if ((_filterType & (int)GeomType.vf_face) > 0)
            {
                _mouse.AddToLocateFilter((int)SolidEdgeConstants.seLocateFilterConstants.seLocateFace);
                // 置为2，使选择壳
                _mouse.GroupLocateMode = 2;
            }

            if ((_filterType & (int)GeomType.vf_body) > 0)
            {
                _mouse.AddToLocateFilter((int)SolidEdgeConstants.seLocateFilterConstants.seLocateBody);
            }
            _status = SelectStatus.Running;
            _partDoc.Application.StatusBar = _prompStr;
            _selOpt.Show();
            IntPtr hwnd = new WindowInteropHelper(_selOpt).Handle;
            IntPtr targetHwnd = (IntPtr)(_partDoc.Application.ActiveWindow as SolidEdgeFramework.Window).hWnd;
            SetWindowPos(hwnd, targetHwnd, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
        }

        void SolidEdgeFramework.ISECommandEvents.Deactivate()
        {
            _status = SelectStatus.Cancel;
            _selOpt.Close();
        }

        void SolidEdgeFramework.ISECommandEvents.Terminate()
        {

            DisconnectEventSource();

           
            if (_status != SelectStatus.Success)
            {
                _status = SelectStatus.Failed;
            }
            _selOpt.Close();
        }

        void SolidEdgeFramework.ISECommandEvents.Idle(int lCount, out bool pbMore)
        {
            pbMore = false;
        }

        void SolidEdgeFramework.ISECommandEvents.KeyDown(ref short KeyCode, short Shift)
        {

        }

        void SolidEdgeFramework.ISECommandEvents.KeyPress(ref short KeyAscii)
        {

        }

        void SolidEdgeFramework.ISECommandEvents.KeyUp(ref short KeyCode, short Shift)
        {

        }

        void ISEMouseEvents.MouseDown(short sButton, short sShift, double dX, double dY, double dZ, object pWindowDispatch, int lKeyPointType, object pGraphicDispatch)
        {
 
        }

        void ISEMouseEvents.MouseUp(short sButton, short sShift, double dX, double dY, double dZ, object pWindowDispatch, int lKeyPointType, object pGraphicDispatch)
        {
           
        }

        protected virtual void OnMouseMove(short sButton, short sShift, double dX, double dY, double dZ, object pWindowDispatch, int lKeyPointType, object pGraphicDispatch)
        {
            _partDoc.Application.StatusBar = _prompStr;
        }
        void ISEMouseEvents.MouseMove(short sButton, short sShift, double dX, double dY, double dZ, object pWindowDispatch, int lKeyPointType, object pGraphicDispatch)
        {

        }



        void ISEMouseEvents.MouseClick(short sButton, short sShift, double dX, double dY, double dZ, object pWindowDispatch, int lKeyPointType, object pGraphicDispatch)
        {
            // 1为左键 2为右键
            if(sButton==2 && !_isSingleSelect)
            {
                // 右键单击，表示确认选这么多个
                if(_eleIdArr.Count>0)
                {
                  _status = SelectStatus.Success;
                }
                _partDoc.Application.AbortCommand(true);
            }

            if (null!= pGraphicDispatch)
            {
                UInt64 eleId = _partDoc.GetEntityID(pGraphicDispatch);
                if (eleId == UInt64.MaxValue)
                {
                    _status = SelectStatus.Failed;
                    return;
                }
                dynamic dynamic = pGraphicDispatch;
                SolidEdgeGeometry.GNTTypePropertyConstants type = (SolidEdgeGeometry.GNTTypePropertyConstants)dynamic.Type;
                


                ElementDesc eleDesc = new ElementDesc() { Id = eleId,Type=type,Geometry=pGraphicDispatch };

                if (!_eleIdArr.Contains(eleDesc))
                {
                    _eleIdArr.Add(eleDesc);
                    if(!_isSingleSelect)
                    {
                        _partDoc.Application.ActiveSelectSet.Add(pGraphicDispatch);
                    }
                }
                if (_isSingleSelect)
                {
                    // 单选时,选中一个就退出
                    _status = SelectStatus.Success;
                    _partDoc.Application.AbortCommand(true);
                }
                else
                {
                    _viewModel.ElementDescArr = _eleIdArr;
                }
            }


        }

        void ISEMouseEvents.MouseDblClick(short sButton, short sShift, double dX, double dY, double dZ, object pWindowDispatch, int lKeyPointType, object pGraphicDispatch)
        {

        }

        void ISEMouseEvents.MouseDrag(short sButton, short sShift, double dX, double dY, double dZ, object pWindowDispatch, short DragState, int lKeyPointType, object pGraphicDispatch)
        {

        }

        void ISELocateFilterEvents.Filter(object pGraphicDispatch, out bool vbValid)
        {
            vbValid = true;
        }

        public void Dispose()
        {
            Marshal.ReleaseComObject(_mouse);
            Marshal.ReleaseComObject(_partDoc);
            _partDoc = null;
            _mouse = null;
        }

        void ISelectOptionChang.OnOptionChange(FaceChainMode mode)
        {
            if(mode == FaceChainMode.Single)
            {
                _mouse.GroupLocateMode = 0;
            }
            else if ((_filterType & (int)GeomType.vf_face) > 0)
            {
                _mouse.GroupLocateMode = 2;
            } else if ((_filterType & (int)GeomType.vf_body)>0)
            {
                _mouse.GroupLocateMode = 1;
            }
        }
    }

}
